/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

// Gobal Stuff
var watchID = null;

var app = {
    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicity call 'app.receivedEvent(...);'
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },
    // Update DOM on a Received Event
    receivedEvent: function(id) {
        var parentElement = document.getElementById(id);
        var listeningElement = parentElement.querySelector('.listening');
        var receivedElement = parentElement.querySelector('.received');

        listeningElement.setAttribute('style', 'display:none;');
        receivedElement.setAttribute('style', 'display:block;');

        console.log('Received Event: ' + id);
    }
};

function showPopup(){
    var value = document.getElementById("fibo").value;
    fib(parseInt(value));
}

function fib (iterations)
{
    var i = 0;
    var fib1 = 0;
    var start1 = new Date().getTime();
    
    do
    {
    //fib 1 test
    fib1 = fibonacci1(1000);
    i++;
    }
    while(i<iterations);
    
    var end1 = new Date().getTime();
    var executionTime1 = end1 - start1;
    $('#fib1').text("Fib1 Time: " + executionTime1 + "ms");
    
    
    //Section Fib 2
    var i = 0;
    var fib2 = 0;
    var start2 = new Date().getTime();
    
    do
    {
        //fib 2 test
        fib2 = fibonacci2(1000);
        i++;
    }
    while(i<iterations);
    
    var end2 = new Date().getTime();
    var executionTime2 = end2 - start2;
    $('#fib2').text("Fib2 Time: " + executionTime2 + "ms");
    
    //Section Fib 3
    var i = 0;
    var fib3 = 0;
    var start3 = new Date().getTime();
    
    do
    {
        //fib 3 test
        fib3 = fibonacci3(1000);
        i++;
    }
    while(i<iterations);
    
    var end3 = new Date().getTime();
    var executionTime3 = end3 - start3;
    $('#fib3').text("Fib3 Time: " + executionTime3 + "ms");
    
    //Section Fib 4
    var i = 0;
    var fib4 = 0;
    var start4 = new Date().getTime();
    
    do
    {
        //fib 4 test
        fib4 = fibonacci4(1000);
        i++;
    }
    while(i<iterations);
    
    var end4 = new Date().getTime();
    var executionTime4 = end4 - start4;
    $('#fib4').text("Fib4 Time: " + executionTime4 + "ms");
    
}

// No recursion or looping, just math

function fibonacci1(n) {
    return Math.round(Math.pow((Math.sqrt(5) + 1) / 2, Math.abs(n)) / Math.sqrt(5)) * (n < 0 && n % 2 ? -1 : 1);
}


// Using a loop and an array

function fibonacci2(n) {
    var i, fibs = [0, 1];
    for (i = 0; i++ < n;) {
        fibs.push(fibs[0] + fibs[1]);
        fibs.shift();
    }
    return fibs[0];
}


// like fibonacci1 but with caching and exp instead of pow
var fibonacci3 = (function(Math) {
                  var sqrt5 = Math.sqrt(5),
                  lnphi = Math.log(1 + sqrt5) - Math.LN2,
                  exp = Math.exp,
                  round = Math.round;
                  
                  return function(n) {
                  return n <= 2 ? n && 1 : round(exp(lnphi * n) / sqrt5);
                  };
                  })(Math);


// linear recursion

function fibonacci4(n) {
    function rek(n, a, b) {
        return n <= 1 ? a + b : rek(n - 1, a + b, a);
    }
    
    return n <= 2 ? n && 1 : rek(n - 1, 1, 0);
}

function calcFac(){
    var value = document.getElementById("fac").value;
    Factorial(parseInt(value));
}

function Factorial(iterations){
    var i = 0;
    var fac1 = 0;
    var start1 = new Date().getTime();
    
    do
    {
        //fac 1 test
        fac1 = Factorial1(100);
        i++;
    }
    while(i<iterations);
    
    var end1 = new Date().getTime();
    var executionTime1 = end1 - start1;
    $('#fac1').text("Factorial1 Time: " + executionTime1 + "ms");
    
    //Section Fac 2
    var i = 0;
    var fac2 = 0;
    var start2 = new Date().getTime();
    
    do
    {
        //fib 2 test
        fac2 = Factorial2(100);
        i++;
    }
    while(i<iterations);
    
    var end2 = new Date().getTime();
    var executionTime2 = end2 - start2;
    $('#fac2').text("Factorial2 Time: " + executionTime2 + "ms");

}


//Recursive Factorial
function Factorial1(num){
        if (num === 0)
        { return 1; }
        else
        { return num * Factorial1( num - 1 ); }
}

//Iterative Factorial
function Factorial2(num)
{
    var rval=1;
    for (var i = 2; i <= num; i++)
        rval = rval * i;
    return rval;
}


// Start watching the acceleration
//
function startWatch() {
    
    // Update acceleration every 100ms
    var options = { frequency: 100 };
    console.log("Start Acceleration Watch");
    watchID = navigator.accelerometer.watchAcceleration(accelerometerSuccess, accelerometerError, options);
    console.log("watchID: " + watchID);
    }

// Stop watching the acceleration
//
function stopWatch() {
    console.log("Stop Watch invoked with watchID: " + watchID);
    if (watchID) {
        navigator.accelerometer.clearWatch(watchID);
        watchID = null;
    }
}


function accelerometerSuccess(acceleration){
    console.log("X: " + acceleration.x + " Y: " + acceleration.y + " Z: " + acceleration.z);
    $('#XAxis').text("X-Axis: " + acceleration.x);
    $('#YAxis').text("Y-Axis: " + acceleration.y);
    $('#ZAxis').text("Z-Axis: " + acceleration.z);
    $('#Timestamp').text("Timestamp: " + acceleration.timestamp);
}

function accelerometerError(error){
    alert("Error");
}

// Camera
function getPicture(){
    navigator.camera.getPicture(onPictureSuccess, onPictureFail, { quality: 50,
                                destinationType: Camera.DestinationType.DATA_URL
                                });
}

function onPictureSuccess(imageData){
    var image = document.getElementById('imagetaken');
    image.src = "data:image/jpeg;base64," + imageData;
}

function onPictureFail(message) {
    alert('Failed because: ' + message);
}

//Notifications

function alertCustom(){
    console.log("alert()");
    navigator.notification.alert("Test Alert", alertCallback, "Alert", "Done")
}

function alertCallback(){
    console.log("alertCallback()");
}

function confirm(){
    navigator.notification.confirm(
                                   'You are the winner!', // message
                                   confirmCallback,            // callback to invoke with index of button pressed
                                   'Game Over',           // title
                                   'Restart,Exit'         // buttonLabels
                                   );
}

function confirmCallback(){
    console.log("confirmCallback()");
}

function prompt(){
    navigator.notification.prompt(
                                  'Please enter your name',  // message
                                  onPrompt,                  // callback to invoke
                                  'Registration',            // title
                                  ['Ok','Exit'],             // buttonLabels
                                  'John Appleseed'                 // defaultText
                                  );
}

function onPrompt(results) {
    alert("You selected button number " + results.buttonIndex + " and entered " + results.input1);
}

function beep(){
    navigator.notification.beep(3);
}
function vibrate(){
    navigator.notification.vibrate(2000);
}